package com.sykj.controller;

import com.sykj.bean.bis.BisCustomUser;
import com.sykj.bean.bis.BisNurseBag;
import com.sykj.bean.card.CardGame;
import com.sykj.bean.card.CardUserGame;
import com.sykj.bean.card.CardUserHit;

import com.sykj.config.mq.LuaScript;
import com.sykj.service.BisCustomUserService;
import com.sykj.service.CardGameService;
import com.sykj.util.RabbitKeys;
import com.sykj.util.RedisByhUtils;
import com.sykj.util.RedisKeys;

import com.sykj.util.reponse.CommonEnum;
import com.sykj.util.reponse.ResultBody;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @program: hongbao
 * @description: 抽奖模块接口
 * @author: qiaoli
 * @create: 2020-08-05 20:44
 */
@RestController
@RequestMapping("/act")
public class ActController {

    @Autowired
    RedisByhUtils redisUtil;
    @Autowired
    CardGameService cardGameService;
    @Autowired
    RabbitTemplate  rabbitTemplate;
    @Autowired
    LuaScript luaScript;
    @Autowired
    BisCustomUserService service;
    /**
     * 功能描述:  抽奖接口，
     * @Param: [gameid, userid, request] 参数一 为  活动id  ， 参数二 为  用户id
     * @Return: java.lang.Object
     * @Author: Feiwo Sicun
     * @Date: 2020/8/6 9:04
     */
@GetMapping("/go/{gameid}/{userid}")
    public ResultBody act(@PathVariable(value = "gameid")Integer gameid, @PathVariable(value = "userid")String userid, HttpServletRequest request){
          Date now=new Date();
         // 获取活动的基本信息
    CardGame game = (CardGame) redisUtil.get(RedisKeys.INFO + gameid);


   // 判断当前活动是否开始
    // 若活动信息还没有加载到redis中 则请求无效
    // 若活动已加载，即预热已完成， 但是开始时间大于 当前时间 也无效
      if(game== null || game.getStarttime().after(now)){
          return new ResultBody(CommonEnum.HONG_ACT_NOT_START);
      }
      //判断活动是否已经结束：
    if(now.after(game.getEndtime())){
        return  new ResultBody(CommonEnum.HONG_ACT_END);

    }
    // 若都没有则 获取当前用户信息
    BisCustomUser bisCustomUser = service.getById(userid);
    // 从reids 中 读取共享session 查看用户是否登录
    boolean b = redisUtil.hasKey(RedisKeys.SESSIONID + userid);

    String  id="";
    if(b){
        id=  redisUtil.get(RedisKeys.SESSIONID+userid).toString();

    }

    // 判断用户是否登陆id
    if( bisCustomUser== null || !userid.equals(id) ){
       return   new ResultBody(CommonEnum.USER_NOT_LONG);
    }else{

    // 在此处可用 前端session 报错用户信息，也可以后台 session 来保存  判断用户是否登录
   // 判断用户是否第一次抽奖 若为第一次 将其信息插入reids中 若不是则继续执行
    if (!redisUtil.hasKey(RedisKeys.USERGAME+bisCustomUser.getCustomUserId()+"_"+gameid)){
        redisUtil.set(RedisKeys.USERGAME+bisCustomUser.getCustomUserId()+"_"+gameid,1,(game.getEndtime().getTime() - now.getTime())/1000);
        //持久化抽奖记录，扔给消息队列处理
        CardUserGame userGame = new CardUserGame();
        userGame.setUserid(bisCustomUser.getCustomUserId());
        userGame.setGameid(gameid);
        userGame.setCreatetime(new Date());
        rabbitTemplate.convertAndSend(RabbitKeys.QUEUE_PLAY,userGame);
    }

       }
    //用户已中奖次数
    Integer count = (Integer) redisUtil.get(RedisKeys.USERHIT+gameid+"_"+bisCustomUser.getCustomUserId());

   // 若是第一次抽奖 将其初始化为0，设置有效时间为当前时间于活动结束时间之差
    if (count == null){
        count = 0;
        redisUtil.set(RedisKeys.USERHIT+gameid+"_"+bisCustomUser.getCustomUserId(),count,(game.getEndtime().getTime() - now.getTime())/1000);
    }
    //设置最大中奖次数：
    Integer maxcount=1;
    //次数对比
    if (maxcount > 0 && count >= maxcount){
        //如果达到最大次数，不允许抽奖
        return new ResultBody(CommonEnum.HONG_ACT_CI);
    }
    // 若以上校验全部通过，进入准许抽奖
    // 从 redis 队列左侧抽取一个token  进行验证
//    Long token = (Long) redisUtil.leftPop(RedisKeys.TOKENS+gameid);
//    if(token== null){
//        // 表明令牌已用完，奖品抽完了
//        return "奖品已抽光";
//    }
//    //若拿到token 判断token令牌时间戳的大小 看是否中奖
//    //因存入token是的时间戳*1000 ，故在获取时要除以1000
//    if(now.getTime()< token/1000){
//        //当前时间小于令牌时间戳，说明奖品未到发放时间点，放回令牌，返回未中奖
//        redisUtil.leftPush(RedisKeys.TOKENS+gameid,token);
//        return "未中奖";
//
//    }
//使用lua脚本

    Long token=luaScript.tokenCheck(RedisKeys.TOKENS+gameid,String.valueOf(now.getTime()));

     if(token == 0){
         return new ResultBody(CommonEnum.HONG_ACT_MAX);
     }
     else if(token == 1){
         return new ResultBody(CommonEnum.HONG_ACT_NO);
     }

    // 若以上逻辑都通过，说明中奖了
    // 抽取中奖的奖品
    BisNurseBag product = (BisNurseBag) redisUtil.get(RedisKeys.TOKEN + gameid +"_"+token);
    //中奖次数加1
    redisUtil.incr(RedisKeys.USERHIT+gameid+"_"+bisCustomUser.getCustomUserId(),1);
//投放消息给队列，中奖后的耗时业务，交给消息模块处理
    CardUserHit hit = new CardUserHit();
    hit.setGameid(gameid);
    hit.setHittime(now);
    hit.setProductid(product.getBagId());
    hit.setUserid(bisCustomUser.getCustomUserId());
    rabbitTemplate.convertAndSend(RabbitKeys.EXCHANGE_DIRECT, RabbitKeys.QUEUE_HIT, hit);


    return new ResultBody(CommonEnum.HONG_ACT_OK);
    }
    @GetMapping("/info/{gameid}")
    public Map info(@PathVariable int gameid){
        Map map = new LinkedHashMap<>();
        map.put(RedisKeys.INFO+gameid,redisUtil.get(RedisKeys.INFO+gameid));
        List<Object> tokens = redisUtil.lrange(RedisKeys.TOKENS+gameid,0,-1);
        Map tokenMap =new LinkedHashMap();
        tokens.forEach(o -> tokenMap.put(
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(Long.valueOf(o.toString())/1000)),
                redisUtil.get(RedisKeys.TOKEN + gameid +"_"+o))
        );
        map.put(RedisKeys.TOKENS+gameid,tokenMap);
//        map.put(RedisKeys.MAXGOAL+gameid,redisUtil.hmget(RedisKeys.MAXGOAL+gameid));
//        map.put(RedisKeys.MAXENTER+gameid,redisUtil.hmget(RedisKeys.MAXENTER+gameid));
         Map<String ,Object> s=new HashMap<>();
         s.put("200",map);
        return s;
    }
}
